package controller;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Observable;
import java.util.Observer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import model.Model;
import model.game2048.Game2048Model;
import model.game2048solver.Solver;
import view.View;
import view.game2048.Game2048View;
/**
 * The presenter class is one layer out of three of the MVP design pattern.
 * The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.
 * 
 * @author Peled Eldan
 * @author Daniel Manor
 */
public class Presenter implements Observer
{
	// Data Members //
	private Model model;
	private View ui;
    private Solver solver;
	public Presenter(Model model, View ui) throws InterruptedException
	{
		this.model = model;
		this.ui = ui;
	}
	public Presenter(Model model, View ui,Solver solver) throws InterruptedException
	{
		this.model = model;
		this.ui = ui;
		this.solver=solver;
	}

	@Override
	public void update(Observable obs, Object obj)
	{
		// If the model started the update method and the obj is false, initiate gameOver.
		if ((obs.getClass().equals(this.model.getClass()) && (obj != null) && ((boolean)obj == false)))
		{
			int[][] tempArr = new int[model.getRows()][model.getCols()];
			tempArr[0][0] = Game2048View.GAME_OVER;
			ui.displayData(tempArr, model.getScore());
		}
		// If the model started the update method
		else if (obs.getClass().equals(this.model.getClass()))
		{
			ui.displayData(model.getData(), model.getScore());
		}
		// If the ui started the update method
		else if(obs.getClass().equals(this.ui.getClass()))
		{
			int userCommand = 0;
			
			if(ui.getUserCommand()==100){
			
				userCommand = model.connectToServer();
			}
			
			else{
			userCommand = ui.getUserCommand();
			}
			switch (userCommand)
			{ 
			case -1: 
			break;
			case 101: solver.findBestMove(model.getData());
			break;
			case 0: model.moveUp();
			break;
			case 1: model.moveDown();
			break;
			case 2: model.moveLeft();
			break;
			case 3: model.moveRight();
			break;
			case 4: model.startGame();
			break;
			case 77: model.moveUpLeft();
			break;
			case 99: model.moveUpRight();
			break;
			case 11: model.moveDownLeft();
			break;
			case 33: model.moveDownRight();
			break;
			
			case 5: model.undo();
			break;
			case 6:
				String saveLocation = ui.getSaveLocation();
				if (saveLocation != null)
					model.save(saveLocation);
			break;
			case 7:
				String loadLocation = ui.getLoadLocation();
				if (loadLocation != null)
					model.load(loadLocation);
			break;
				case 16:
				model.mute();
				break;
				case 666:
				model.changeSong();
				break;
			default:
				try					{	throw (new Exception("Wrong User Command."));	}
				catch (Exception e)	{	e.printStackTrace();											}
				break;

			}		
		}
		else if(obs.getClass().equals(this.solver.getClass())){
			int move = solver.getBestMove();
			
			switch (move)
			{ 
			
			case -1: 
			break;
			case 0: model.moveUp();
			
			break;
			case 1: model.moveDown();
		
			break;
			case 2: model.moveLeft();
		
			break;
			case 3: model.moveRight();
			
			break;
			
			
			}
		}
		else
		{
			try 				{	throw (new Exception("Unknown object class started the update method."));	}
			catch (Exception e) {	e.printStackTrace();														}
		}

	}
}
